Three changes:
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sat, 13 Dec 2003 07:13:46 +0000 (07:13 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sat, 13 Dec 2003 07:13:46 +0000 (07:13 +0000)
1) Lay groundwork in GPX parser for context sensitive switching.
2) Add route reversal.
3) move painful test to 'torture' target from testo (you're welcome, Ron)

gpsbabel/Makefile
gpsbabel/defs.h
gpsbabel/filter_vecs.c
gpsbabel/gpx.c
gpsbabel/queue.h
gpsbabel/reverse_route.c [new file with mode: 0644]
gpsbabel/route.c
gpsbabel/testo
gpsbabel/torture_test [new file with mode: 0755]
gpsbabel/vmem.c [new file with mode: 0644]

index 53ce2e684233a8336488628affb7356c85c879f7..62944f09049c3b12f3e9e0fc6625a2629b46d07d 100644 (file)
@@ -20,7 +20,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \
        xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o \
        gpilots.o saroute.o navicache.o psitrex.o geoniche.o
 
-FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o
+FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o
 
 JEEPS=jeeps/gpsapp.o jeeps/gpscom.o \
        jeeps/gpsmath.o jeeps/gpsmem.o  \
@@ -33,7 +33,7 @@ JEEPS=jeeps/gpsapp.o jeeps/gpscom.o \
 COLDSYNC=coldsync/util.o coldsync/pdb.o
 
 LIBOBJS = queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o \
-          csv_util.o grtcirc.o \
+          csv_util.o grtcirc.o vmem.o \
        $(COLDSYNC) $(GARMIN) $(JEEPS) $(FMTS) $(FILTERS)
 OBJS = main.o $(LIBOBJS)
 
@@ -51,6 +51,13 @@ main.o:
 clean:
        rm -f $(OBJS) gpsbabel gpsbabel.exe
 
+check:
+       ./testo
+
+torture:
+       ./testo
+       ./torture_test
+
 #
 # This will only work on UNIX-like substances.
 #
@@ -70,10 +77,10 @@ dep:
        (echo -n "internal_styles.c: mkstyle.sh " ; echo style/*.style ; /bin/echo -e '\t./mkstyle.sh > $@ || (rm -f $@ ; exit 1)' ) >> /tmp/dep
        echo Edit Makefile and bring in /tmp/dep
 
-VERSIONU=1_1_1_beta10082003
-VERSIOND=1.1.1_beta10082003
-VERSIONU=1_2_1
-VERSIOND=1.2.1
+VERSIONU=1_2_1_beta12132003
+VERSIOND=1.2.1_beta12132003
+#VERSIONU=1_2_1
+#VERSIOND=1.2.1
 
 release:
        ./chkdoc
index 2b5ee3c6af989e52f062fd7eec6f15b30ea59b0f..45cad67feb32776b084b79cbca0e681a4f01d5bb 100644 (file)
@@ -245,6 +245,15 @@ void setshort_mustupper(void *, int n);
 void setshort_mustuniq(void *, int n);
 void setshort_whitespace_ok(void *, int n);
 
+typedef struct vmem {
+       void *mem;              /* visible memory object */
+       size_t size;            /* allocated size of object */
+} vmem_t;
+vmem_t         vmem_alloc(size_t);
+void   vmem_free(vmem_t*);
+void   vmem_realloc(vmem_t*, size_t);
+
+
 #define ARGTYPE_UNKNOWN  0
 #define ARGTYPE_INT      0x00000001
 #define ARGTYPE_FLOAT    0x00000002
index 3da4816f95e1c130392e271d5ffdbcf16e1aafef..6453dc8de66f68aa611c2502d420d957f2fa161c 100644 (file)
@@ -34,6 +34,7 @@ extern filter_vecs_t duplicate_vecs;
 extern filter_vecs_t arcdist_vecs;
 extern filter_vecs_t polygon_vecs;
 extern filter_vecs_t routesimple_vecs;
+extern filter_vecs_t reverse_route_vecs;
 
 static
 fl_vecs_t filter_vec_list[] = {
@@ -67,6 +68,11 @@ fl_vecs_t filter_vec_list[] = {
                "simplify",
                "Simplify routes",
        },
+       {
+               &reverse_route_vecs,
+               "reverse",
+               "Reverse stops within routes",
+       },
         {
                NULL,
                NULL,
index 09f29e3c8196487156fc700ad9aad600edf14644..dfcce94180e7533e6863142c354651019da16e9e 100644 (file)
@@ -63,6 +63,7 @@ static const char *gpx_creator;
 
 static char *gpx_email = NULL;
 static char *gpx_author = NULL;
+vmem_t current_tag;
 
 static waypoint *wpt_tmp;
 static FILE *fd;
@@ -84,6 +85,84 @@ static route_head *rte_head;
 #define MYNAME "GPX"
 #define MY_CBUF 4096
 
+typedef enum {
+       tt_unknown = 0,
+       tt_ele,
+       tt_name,
+       tt_gpx,
+       tt_email,
+       tt_author,
+       tt_wpt,
+       tt_desc,
+       tt_cmt,
+       tt_rte,
+       tt_rtept,
+       tt_trk,
+       tt_trkpt,
+       tt_number,
+       tt_time,
+       tt_url,
+       tt_urlname,
+       tt_sym,
+       tt_cache_type,
+       tt_cache_name,
+       tt_cache_container,
+       tt_cache_difficulty,
+       tt_cache_terrain,
+       tt_cache_log,
+       tt_cache_log_wpt,
+       tt_cache_exported,
+       tt_cache_travelbugs
+} tag_type;
+
+typedef struct tag_mapping {
+       tag_type tag_type;
+       const char *tag_name;
+} tag_mapping;
+
+tag_mapping tag_map[] = {
+       { tt_ele, "ele" },
+       { tt_name, "name" },
+       { tt_gpx, "gpx" },
+       { tt_email, "email" },
+       { tt_author, "author" },
+       { tt_wpt, "wpt" },
+       { tt_desc, "desc" },
+       { tt_cmt, "cmt" },
+       { tt_rte, "rte" },
+       { tt_rtept, "rtept" },
+       { tt_trk, "trk" },
+       { tt_trkpt, "trkpt" },
+       { tt_number, "number" },
+       { tt_time, "time" },
+       { tt_url, "url" },
+       { tt_urlname, "urlname" },
+       { tt_sym, "sym" },
+       { tt_cache_type, "groundspeak:type" },
+       { tt_cache_name, "groundspeak:name" },
+       { tt_cache_container, "groundspeak:container" },
+       { tt_cache_difficulty, "groundspeak:difficulty" },
+       { tt_cache_terrain, "groundspeak:terrain" },
+       { tt_cache_log, "groundspeak:log" },
+       { tt_cache_log_wpt, "groundspeak:log_wpt" },
+       { tt_cache_exported, "groundspeak:exported" },
+       { tt_cache_travelbugs, "groundspeak:travelbugs" },
+       {0}
+};
+
+static tag_type
+get_tag(const char *t)
+{
+       tag_mapping *tm;
+
+        for (tm = tag_map; tm->tag_type != 0; tm++) {
+               if (0 == strcmp(tm->tag_name, t)) {
+                       return tm->tag_type;
+               }
+       }
+       return tt_unknown;
+}
+
 static void
 tag_gpx(const char **attrv)
 {
@@ -232,114 +311,124 @@ tag_log_wpt(const char **attrv)
 static void
 gpx_start(void *data, const char *el, const char **attr)
 {
-
-       if (strcmp(el, "ele") == 0) {
+       char *e;
+       char *ep;
+       vmem_realloc(&current_tag, strlen(current_tag.mem) + 1 + strlen(el));
+       e = current_tag.mem;
+       ep = e + strlen(e);
+       *ep++ = '/';
+       strcpy(ep, el);
+       switch (get_tag(el)) {
+       case tt_ele:
                in_ele++;
-       } 
-       else if (strcmp(el, "name") == 0) {
+               break;
+       case tt_name:
                in_name ++;
-       } 
-       else if (strcmp(el, "gpx") == 0) {
+               break;
+       case tt_gpx:
                tag_gpx(attr);
-       }
-        else if (strcmp(el, "email") == 0 ) {
+               break;
+       case tt_email:
                in_email++;
-       }
-       else if (strcmp(el, "author") == 0 ) {
+               break;
+       case tt_author:
                in_author++;
-       }
-       else if (strcmp(el, "wpt") == 0) {
+               break;
+       case tt_wpt:
                in_wpt++;
                tag_wpt(attr);
-       } 
-       else if (strcmp(el, "desc") == 0) {
+               break;
+       case tt_desc:
                in_desc++;
-       } 
-       else if (strcmp(el, "cmt") == 0) {
+               break;
+       case tt_cmt:
                in_cmt++;
-       } 
-       else if (strcmp(el, "rte") == 0) {
+               break;
+       case tt_rte:
                rte_head = route_head_alloc();
                route_add_head(rte_head);
                in_rte++;
-       } 
-       else if (strcmp(el, "rtept") == 0) {
+               break;
+       case tt_rtept:
                in_rtept++;
                tag_wpt(attr);
-       } 
-       else if (strcmp(el, "trk") == 0) {
+               break; 
+       case tt_trk:
                trk_head = route_head_alloc();
                route_add_head(trk_head);
                in_trk++;
-       } 
-       else if (strcmp(el, "trkpt") == 0) {
+               break;
+       case tt_trkpt:
                in_trkpt++;
                tag_wpt(attr);
-       } 
-       else if (strcmp(el, "number") == 0) {
+               break;
+       case tt_number:
                in_number++;
-       } 
-       else if (strcmp(el, "time") == 0) {
+               break;
+       case tt_time:
                in_time++;
-       } 
-       else if (strcmp(el, "url") == 0) {
+               break;
+       case tt_url:
                in_url++;
-       } 
-       else if (strcmp(el, "urlname") == 0) {
+               break;
+       case tt_urlname:
                in_urlname++;
-       } 
-       else if (strcmp(el, "sym") == 0) {
+               break;
+       case tt_sym:
                in_icon++;
-       } 
-       else if (strcmp(el, "groundspeak:type") == 0) {
+               break;
+       case tt_cache_type:
                in_gs_type++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (strcmp(el, "groundspeak:name") == 0) {
+               break;
+       case tt_cache_name:
                in_gs_name++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (strcmp(el, "groundspeak:container") == 0) {
+               break;
+       case tt_cache_container:
                in_gs_container++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (strcmp(el, "groundspeak:difficulty") == 0) {
+               break;
+       case tt_cache_difficulty:
                in_gs_diff++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (strcmp(el, "groundspeak:terrain") == 0) {
+               break;
+       case tt_cache_terrain:
                in_gs_terr++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (strcmp(el, "groundspeak:log") == 0) {
+               break;
+       case tt_cache_log:
                in_gs_log++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (strcmp(el, "groundspeak:log_wpt") == 0) {
+               break;
+       case tt_cache_log_wpt:
                in_gs_log_wpt++;
                 if (opt_logpoint)
                    tag_log_wpt(attr);
                in_something_else++;
                start_something_else( el, attr );
-       }
-       else if (strcmp(el, "groundspeak:exported") == 0) {
+               break;
+       case tt_cache_exported:
                in_gs_exported++;
                /* no start_something_else because the old date is eaten */
-       }
-       else if (strcmp(el, "groundspeak:travelbugs") == 0) {
+               break;
+       case tt_cache_travelbugs:
                in_gs_tbugs++;
                in_something_else++;
                start_something_else( el, attr );
-       } 
-       else if (in_wpt) {
-               in_something_else++;
-               start_something_else( el, attr );
+               break;
+       default:
+               if (in_wpt) {
+                       in_something_else++;
+                       start_something_else( el, attr );
+               }
+               break;
        }
 }
 
@@ -461,7 +550,15 @@ xml_parse_time( char *cdatastr )
 static void
 gpx_end(void *data, const char *el)
 {
+       char *s = strrchr(current_tag.mem, '/');
+
+       if (strcmp(s + 1, el)) {
+               fprintf(stderr, "Mismatched tag %s\n", el);
+       }
+       *s = 0;
+
        float x;
+
        if (in_cdata) {
                if (in_name && in_wpt && !in_gs_tbugs) {
                        wpt_tmp->shortname = xstrdup(cdatastr);
@@ -556,84 +653,111 @@ gpx_end(void *data, const char *el)
                in_cdata--;
                memset(cdatastr, 0, MY_CBUF);
        }
-       if (strcmp(el, "wpt") == 0) {
+       switch (get_tag(el)) {
+       case tt_wpt:
                if ( !wpt_tmp->gc_data.exported ) {
                        wpt_tmp->gc_data.exported = file_time;
                }
                waypt_add(wpt_tmp);
                in_wpt--;
                logpoint_ct = 0;
-       } 
-         else if (strcmp(el, "rte") == 0) {
+               break;
+       case tt_rte:
                in_rte--;
-       } else if (strcmp(el, "rtept") == 0) {
+               break;
+       case tt_rtept:
                route_add_wpt(rte_head, wpt_tmp);
                in_rtept--;
-       } else if (strcmp(el, "trk") == 0) {
+               break;
+       case tt_trk:
                in_trk--;
-       } else if (strcmp(el, "trkpt") == 0) {
+               break;
+       case tt_trkpt:
                route_add_wpt(trk_head, wpt_tmp);
                in_trkpt--;
-       } else if (strcmp(el, "number") == 0) {
+               break;
+       case tt_number:
                in_number--;
-       } else if (strcmp(el, "name") == 0) {
+               break;
+       case tt_name:
                in_name--;
-       } else if (strcmp(el, "desc") == 0) {
+               break;
+       case tt_desc:
                in_desc--;
-       } else if (strcmp(el, "email") == 0 ) {
+               break;
+       case tt_email:
                in_email--;
-       } else if (strcmp(el, "author") == 0 ) {
+               break;
+       case tt_author:
                in_author--;
-       } else if (strcmp(el, "cmt") == 0) {
+               break;
+       case tt_cmt:
                in_cmt--;
-       } else if (strcmp(el, "ele") == 0) {
+               break;
+       case tt_ele:
                in_ele--;
-       } else if (strcmp(el, "time") == 0) {
+               break;
+       case tt_time:
                in_time--;
-       } else if (strcmp(el, "url") == 0) {
+               break;
+       case tt_url:
                in_url--;
-       } else if (strcmp(el, "urlname") == 0) {
+               break;
+       case tt_urlname:
                in_urlname--;
-       } else if (strcmp(el, "sym") == 0) {
+               break;
+       case tt_sym:
                in_icon--;
-       } else if (strcmp(el, "groundspeak:type") == 0) {
+               break;
+       case tt_cache_type:
                in_gs_type--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:name") == 0) {
+               break;
+       case tt_cache_name:
                in_gs_name--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:container") == 0) {
+               break;
+       case tt_cache_container:
                in_gs_container--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:difficulty") == 0) {
+               break;
+       case tt_cache_difficulty:
                in_gs_diff--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:terrain") == 0) {
+               break;
+       case tt_cache_terrain:
                in_gs_terr--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:log") == 0) {
+               break;
+       case tt_cache_log:
                in_gs_log--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:log_wpt") == 0) {
+               break;
+       case tt_cache_log_wpt:
                in_gs_log_wpt--;
                in_something_else--;
                end_something_else();
-       } else if (strcmp(el, "groundspeak:exported") == 0) {
+               break;
+       case tt_cache_exported:
                in_gs_exported--;
                /* no end_something_else because the old date is eaten */
-       } else if (strcmp(el, "groundspeak:travelbugs") == 0) {
+               break;
+       case tt_cache_travelbugs:
                in_gs_tbugs--;
                in_something_else--;
                end_something_else();
-       } else if (in_wpt) {
+               break;
+       default:
+               if (in_wpt) {
                in_something_else--;
                end_something_else();
+               }
        }
 }
 
@@ -726,6 +850,7 @@ gpx_rd_init(const char *fname)
 
 
        file_time = 0;
+       current_tag = vmem_alloc(1);
        
        psr = XML_ParserCreate(NULL);
        if (!psr) {
@@ -740,6 +865,7 @@ gpx_rd_init(const char *fname)
 static void
 gpx_rd_deinit(void)
 {
+       vmem_free(&current_tag);
        if ( cdatastr ) {
                xfree(cdatastr);
                cdatastr = NULL;
index d7bfffd179c3f9974c0bd20945178f7c39fda4b1..7392ce6d22ddbe6ac3bac9387c8ac53f5056c537 100644 (file)
@@ -35,6 +35,8 @@ queue * dequeue(queue *element);
 
 #define ENQUEUE_TAIL(listhead, element) \
                enqueue(element, (listhead)->prev)
+#define ENQUEUE_HEAD(listhead, element) \
+               enqueue(element, listhead)
 
 #define QUEUE_FOR_EACH(listhead, element, tmp) \
        for ((element) = QUEUE_FIRST(listhead); \
diff --git a/gpsbabel/reverse_route.c b/gpsbabel/reverse_route.c
new file mode 100644 (file)
index 0000000..b9d8824
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+    Route reversal filter.
+
+    Copyright (C) 2003 Robert Lipe, robertlipe@usa.net
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#include <stdio.h>
+#include "defs.h"
+
+#define MYNAME "Route reversal filter"
+
+static
+arglist_t reverse_route_args[] = {
+       {0, 0, 0, 0}
+};
+
+void 
+reverse_route_head( const route_head *rte ) 
+{
+       route_reverse(rte);
+}
+
+void 
+reverse_route_process( void ) 
+{
+       route_disp_all( reverse_route_head, NULL, NULL );
+}
+
+void
+reverse_route_init(const char *args) 
+{
+       switch (global_opts.objective) {
+               case rtedata: break;
+               case trkdata: break;
+               default:
+                       fatal(MYNAME ": This filter only works in track "
+                                       "or route (-t or -r) mode.");
+       }
+}
+
+void
+reverse_route_deinit(void) 
+{
+       /* do nothing */
+}
+
+filter_vecs_t reverse_route_vecs = {
+       reverse_route_init,
+       reverse_route_process,
+       reverse_route_deinit,
+       reverse_route_args
+};
index 70c597bb96dbafcbc93c928303535f4a07ddb93c..74cfd57a00f42a5b8aca90612718a10c165161dd 100644 (file)
@@ -96,13 +96,28 @@ void
 route_disp (const route_head *rh, waypt_cb cb )
 {
        queue *elem, *tmp;
+       if (!cb)  {
+               return;
+       }
        QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
                waypoint *waypointp;
                waypointp = (waypoint *) elem;
                        (*cb)(waypointp);
        }
                
-}      
+}
+
+void 
+route_reverse(const route_head *rte_hd)
+{
+       /* Cast away const-ness */
+       route_head *rh = (route_head *) rte_hd;
+       queue *elem, *tmp;
+       QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
+               ENQUEUE_HEAD(&rh->waypoint_list, dequeue(elem));
+       }
+}
+
 void 
 route_disp_all(route_hdr rh, route_trl rt, waypt_cb wc)
 {
@@ -110,9 +125,9 @@ route_disp_all(route_hdr rh, route_trl rt, waypt_cb wc)
        QUEUE_FOR_EACH(&my_route_head, elem, tmp) {
                const route_head *rhp;
                rhp = (route_head *) elem;
-               (*rh)(rhp);
+               if (rh) (*rh)(rhp);
                route_disp(rhp, wc);
-               (*rt)(rhp);
+               if (rt) (*rt)(rhp);
        }
 }
 void
index 34292c02c21cb1ef036b16b9047227278cbc408a..63264d75a0bcfc60b2387aef6c9c2c663ffed235 100755 (executable)
@@ -428,18 +428,25 @@ ${PNAME} -r -i gpx -f reference/route/route.gpx \
 compare ${TMPDIR}/simplify.txt reference/simplify_output.txt
 
 #
-# This is  nasty.   If we have a dictionary handy, treat it as a list of
-# waypoints and reduce all the names to eight characters.   Fewer chars
-# results in lost waypoints currently and that's a defect.
-#
-DICT=/usr/share/dict/words
-if [ -f $DICT ]; 
-then
-       WORDS=`cat $DICT | wc -l`
-       SWORDS=`${PNAME} -i gpsdrive -f $DICT -o gpsdrive,snlen=8 -F /dev/fd/1 | wc -l`
-       if [ $WORDS -ne $SWORDS ];
-       then
-               echo "Shortname reduction failed."
-               exit 1  
-       fi
-fi
+# Route reversal filter.   Do it twice and be sure we get what we
+# started with.
+#
+rm -f ${TMPDIR}/reverse1.arc ${TMPDIR}/reverse2.arc ${TMPDIR}/reference.arc
+${PNAME} -r -i gpx -f reference/route/route.gpx \
+         -o arc -F ${TMPDIR}/reference.arc
+${PNAME} -r -i gpx -f reference/route/route.gpx \
+         -x reverse \
+         -o arc -F ${TMPDIR}/reverse1.arc
+${PNAME} -r -i gpx -f reference/route/route.gpx \
+         -x reverse \
+         -x reverse \
+         -o arc -F ${TMPDIR}/reverse2.arc
+# Verify the first and last are the same
+compare ${TMPDIR}/reference.arc  ${TMPDIR}/reverse2.arc
+# Verify the first and second are different.
+${DIFF}  ${TMPDIR}/reverse1.arc  ${TMPDIR}/reverse2.arc > /dev/null && {
+               echo ERROR Failed reversal test.
+               exit 1
+}
+
+exit 0
diff --git a/gpsbabel/torture_test b/gpsbabel/torture_test
new file mode 100755 (executable)
index 0000000..66095cf
--- /dev/null
@@ -0,0 +1,27 @@
+
+PNAME=${PNAME:-./gpsbabel}
+DIFF=${DIFF:-diff}
+
+TMPDIR=/tmp/gpsbabel.$$
+mkdir -p $TMPDIR
+trap "rm -fr $TMPDIR" 0 1 2 3 15
+
+#
+# This is  nasty.   If we have a dictionary handy, treat it as a list of
+# waypoints and reduce all the names to eight characters.   Fewer chars
+# results in lost waypoints currently and that's a defect.
+#
+DICT=/usr/share/dict/words
+if [ -f $DICT ];
+then
+        WORDS=`cat $DICT | wc -l`
+        SWORDS=`${PNAME} -i gpsdrive -f $DICT -o gpsdrive,snlen=8 -F /dev/fd/1 |
+ wc -l`
+        if [ $WORDS -ne $SWORDS ];
+        then
+                echo "Shortname reduction failed."
+                exit 1
+        fi
+fi
+
+exit 0
diff --git a/gpsbabel/vmem.c b/gpsbabel/vmem.c
new file mode 100644 (file)
index 0000000..bef4d97
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+    vmem utilities.  Manipulate allocated object optimized for 
+    long-term persistence over raw speed.
+
+    Copyright (C) 2003 Robert Lipe, robertlipe@usa.net
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include <stdlib.h>
+
+vmem_t 
+vmem_alloc(size_t size)
+{
+       vmem_t vm;
+       vm.mem = xmalloc(size);
+       vm.size = size;
+       return vm;
+}
+
+void
+vmem_free(vmem_t *vm)
+{
+       xfree(vm->mem);
+       vm->mem = NULL;
+       vm->size = 0;
+       return;
+}
+
+/*
+ * We never shrink a vmem object on the premise that over time, object
+ * will only grow for a while then reach a steady state.
+ */
+void
+vmem_realloc(vmem_t *vm, size_t size)
+{
+       /*
+        * Reallocate only if we must.
+        */
+       if (size > vm->size) {
+               vm->mem = xrealloc(vm->mem, size + 20);
+               vm->size = size;
+       }
+       return;
+}
+
+